package com.logistics.menu.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.logistics.menu.entity.domain.Menu;
import com.logistics.menu.entity.model.MenuPager;
import com.logistics.menu.entity.model.MenuRow;
import com.logistics.menu.entity.model.MenuSave;
import com.logistics.menu.mapper.MenuMapper;
import com.logistics.role.service.RoleMenuService;
import com.logistics.route.entity.model.RouteRow;
import com.logistics.route.service.RouteService;
import com.logistics.utils.aspect.annotation.Insert;
import com.logistics.utils.aspect.annotation.Pager;
import com.logistics.utils.bean.ResultPager;
import com.logistics.utils.constants.Message;
import com.logistics.utils.exception.MessageException;
import com.logistics.utils.message.Manager;
import com.logistics.utils.tool.StringUtils;
import com.logistics.utils.tool.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MenuService extends ServiceImpl<MenuMapper, Menu> {

    @Autowired
    private RoleMenuService roleMenuService;

    @Autowired
    private UserUtils userUtils;

    @Autowired
    private RouteService routeService;

    /**
     * 查找菜单列表分页
     * @param param
     * @return
     */
    @Pager
    public ResultPager pager(MenuPager param){
        IPage page = new Page(param.getCurrent(), param.getPageSize());
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Menu::getParentId, 0);
        if(StringUtils.isNotNull(param.getName())){
            queryWrapper.lambda().like(Menu::getName, param.getName());
        }
        if(StringUtils.isNotNull(param.getType())){
            queryWrapper.lambda().eq(Menu::getType, param.getType());
        }
        IPage<Menu> result = this.page(page, queryWrapper.lambda().orderByDesc(Menu::getCreateTime));
        return new ResultPager(dataFormatter(result.getRecords(), routeService.listAllTile()), (int) result.getTotal());
    }

    /**
     * 查找详细
     * @param id
     * @return
     */
    public MenuRow details(String id) throws MessageException {
        if(StringUtils.isNull(id)){
            throw new MessageException(Manager.getMessage(Message.MSG1005.getCode()));
        }
        return MenuRow.build(this.getOne(new LambdaQueryWrapper<Menu>().eq(Menu::getId, id)));
    }

    /**
     * 保存菜单
     * @param save
     */
    @Insert
    @Transactional
    public void save(MenuSave save){
        if(StringUtils.isNull(save.getId())){
            this.save(Menu.build(save));
        }else{
            this.update(Menu.build(save),
                    new LambdaQueryWrapper<Menu>().eq(Menu::getId, save.getId()));
        }
    }

    /**
     * 删除菜单
     * @param ids
     */
    @Transactional
    public void delete(String ids) throws MessageException {
        if(StringUtils.isNull(ids)){
            throw new MessageException(Manager.getMessage(Message.MSG1005.getCode()));
        }
        List<String> removeIds = getRemoveIds(ids);
        roleMenuService.checkMenuIds(StringUtils.listToString(removeIds, ","));
        this.remove(new LambdaQueryWrapper<Menu>().in(Menu::getId, removeIds));
    }

    /**
     *  获取节点下所有ID
     * @param ids
     * @return
     */
    private List<String> getRemoveIds(String ids){
        List<String> removeId = StringUtils.splitToList(ids , ",");
        List<String> idList = this.list(new LambdaQueryWrapper<Menu>().in(Menu::getParentId, removeId)).
                stream().map(e -> e.getId().toString()).collect(Collectors.toList());
        if(idList.size() > 0)
            removeId.addAll(getRemoveIds(StringUtils.listToString(idList, ",")));
        return removeId;
    }

    /**
     * 根据用户ID查找菜单列表
     * @return
     */
    public List<MenuRow> menus(String device) throws MessageException {
        List<Integer> menuIds = roleMenuService.menuIdsByUserId(userUtils.getUserId());
        List<MenuRow> rows = this.list(new LambdaQueryWrapper<Menu>().
                in(Menu::getId, menuIds).eq(Menu::getUseDevice, device)).stream().map(e -> MenuRow.build(e)).collect(Collectors.toList());
        List<RouteRow> routeRows = routeService.listAllTile();
        return getRoot(rows , routeRows);
    }

    /**
     * 获取所有菜单树形
     * @return
     */
    public List<MenuRow> menuAll(){
        List<Menu> list = this.list();
        return getRoot(list.stream().map(e -> MenuRow.build(e)).collect(Collectors.toList()));
    }

    /**
     * 获取树形结构
     * @param rows
     * @return
     */
    private List<MenuRow> getRoot(List<MenuRow> rows){
        return  getRoot(rows, null);
    }

    /**
     * 获取树形
     * @param rows
     * @param routeRows
     * @return
     */
    private List<MenuRow> getRoot(List<MenuRow> rows, List<RouteRow> routeRows){
        return rows.stream().filter(e -> e.getParentId() == 0).map(e -> {
            e.setChildren(getChildren(e, rows, routeRows));
            if(StringUtils.isNotNull(routeRows)){
                List<RouteRow> routeFilterRow = routeRows.stream().filter(s -> StringUtils.isEquals(s.getId().toString(),
                        e.getRouteId())).collect(Collectors.toList());
                e.setPath(routeFilterRow.stream().map(s -> s.getPath()).collect(Collectors.joining()));
                e.setOpenMethod(routeFilterRow.stream().map(s -> s.getMethod()).collect(Collectors.joining()));
            }
            return e;
        }).collect(Collectors.toList());
    }

    /**
     * 过滤子元素
     * @param root
     * @param allList
     * @param routeRows
     * @return
     */
    private List<MenuRow> getChildren(MenuRow root, List<MenuRow> allList, List<RouteRow> routeRows){
        return allList.stream().filter(e -> e.getParentId() == root.getId())
                .map(e -> {
                    e.setChildren(getChildren(e, allList, routeRows));
                    if(StringUtils.isNotNull(routeRows)){
                        routeRows.stream().forEach(t -> {
                            List<RouteRow> routeFilterRow = routeRows.stream().filter(s -> StringUtils.isEquals(s.getId().toString(),
                                    e.getRouteId())).collect(Collectors.toList());
                            e.setPath(routeFilterRow.stream().map(s -> s.getPath()).collect(Collectors.joining()));
                            e.setOpenMethod(routeFilterRow.stream().map(s -> s.getMethod()).collect(Collectors.joining()));
                        });
                    }
                    return e;
                }).collect(Collectors.toList());
    }


    /**
     * 数据转换
     * @param rows
     * @return
     */
    private List<MenuRow> dataFormatter(List<Menu> rows, List<RouteRow> routeRows){
        List<Menu> allList = this.list();
        return rows.stream().map(e -> MenuRow.build(e))
                .map(e -> {
                    e.setChildren(getChildren(e, allList.stream().map(s -> MenuRow.build(s)).collect(Collectors.toList()), routeRows));
                    return e;
                }).collect(Collectors.toList());
    }
}
